package com.foreveross.crawl.node;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.foreveross.crawl.CrawlContext;

/**
 * 一个节点信息的管理器
 * 主要在于节点划分了很多类型，对于许多的配置信息可以统一获取或者管理，不用去每个worker里面再判断
 * 现阶段慢慢用 ，后面可以统一管理每个节点的信息
 * @author guokenye
 *
 */
public class NodeInfoManager {
	private static NodeInfoManager manager;
	private static Logger logger=LoggerFactory.getLogger(NodeInfoManager.class);
	private Integer type;//节点类型
	private String engineName;//当前节点名称
	private List<Long> channelNotInGroup;//不属于组任务的渠道
	private List<Long> assignNotDoChannels;//指定不做的渠道
	private List<Long> assignDoChannels;//指定做的渠道
	
	
	private NodeInfoManager(){};
	public static NodeInfoManager getInstance() throws Exception{
		if(manager==null){
			logger.error("NodeInfoManager 没有被初始化,无法调用");
			throw new Exception("NodeInfoManager Has Not Init!");
		}
		return manager;
	}
	/**
	 * 初始化必须的节点配置信息
	 * @param nodeType
	 * @param name
	 * @param channelNotInGroupStr
	 * @param assignNotDoChannelsStr
	 * @param assignDoChannelsStr
	 * @throws Exception
	 */
	public static void init(
			Integer nodeType,String name,String channelNotInGroupStr,String assignNotDoChannelsStr,String assignDoChannelsStr)throws Exception{
		
		manager=new NodeInfoManager();
		manager.type=Integer.valueOf(nodeType);
		manager.engineName=name;
		manager.channelNotInGroup=generateIds(channelNotInGroupStr);
		manager.assignNotDoChannels=generateIds(assignNotDoChannelsStr);
		manager.assignDoChannels=generateIds(assignDoChannelsStr);
		switch(nodeType){
		case CrawlContext.NODE_TYPE_1_MAIN:
			logger.info(String.format("该节点引擎[%s]为[主节点]!", name));
			logger.info(String.format("指定非组任务渠道id为 %s", manager.channelNotInGroup.toString()));
			logger.info(String.format("指定不执行任务渠道id为 %s", manager.assignNotDoChannels.toString()));
			break;
		case CrawlContext.NODE_TYPE_2_BASE:
			logger.info(String.format("该节点引擎[%s]为[一般节点]!", name));
			logger.info(String.format("指定不执行任务渠道id为 %s", manager.assignNotDoChannels.toString()));
			break;
		case CrawlContext.NODE_TYPE_3_ASSIGN:
			logger.info(String.format("该节点引擎[%s]为[指定节点]!", name));
			if(manager.assignDoChannels.isEmpty()){
				logger.error("节点没有指定执行渠道id!无法正确初始化");
				manager=null;
				throw new Exception("节点没有指定指定渠道id!");
			}else{
				logger.info(String.format("指定执行任务渠道id为 %s", manager.assignDoChannels.toString()));
			}
			break;
		default:
			logger.error(String.format("该节点引擎[%s]节点类型无法判断!", name));
			manager=null;
			throw new Exception("节点类型无法判断");
		}
	}
	
	
	/**
	 * 判断渠道id是否位于组任务里面
	 * @param id
	 * @return
	 */
	public boolean isChannelInGroup(Long id){
		return !this.channelNotInGroup.contains(id);
	}
	/**
	 * 判断一个渠道是否做任务,根据他对应的type
	 * type在注册的时候已经决定了！
	 * 
	 * @param id
	 * @return
	 */
	public boolean isChannelDoTaskByNodeType(Long id){
		//主节点和一般节点，指定了不做的渠道
		if(this.type==CrawlContext.NODE_TYPE_1_MAIN || this.type==CrawlContext.NODE_TYPE_2_BASE){
			return !this.assignNotDoChannels.contains(id);
		}else{//指定节点指定了做的渠道
			return this.assignDoChannels.contains(id);
		}
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	/**
	 * 将字符串以，分割变成list
	 * 
	 * @param str
	 * @return
	 */
	private static List<Long> generateIds(String idsStr){
		if(idsStr==null || "".equals(idsStr.trim())){return new ArrayList<Long>();}
		Set<Long> temp;
		String[] ids;
		List<Long> result = null;
		try {
			temp=new HashSet<Long>();
			ids=idsStr.split(",");
			for(String id:ids){
				temp.add(Long.valueOf(id));
			}
			result=new ArrayList<Long>(temp);
		} catch (NumberFormatException e) {
			logger.error(e.getMessage());
		}finally{
			ids=null;temp=null;
		}
		return result!=null?result:new ArrayList<Long>();
	}
	public Integer getType() {
		return type;
	}
	public String getEngineName() {
		return engineName;
	}
	
	
	
	
	public List<Long> getChannelNotInGroup() {
		return new ArrayList<Long>(channelNotInGroup);
	}
	public List<Long> getAssignNotDoChannels() {
		return new ArrayList<Long>(assignNotDoChannels);
	}
	public List<Long> getAssignDoChannels() {
		return new ArrayList<Long>(assignDoChannels);
	}
	public static void main(String[] args) throws Exception {
		NodeInfoManager.init(3, "xiaoken _test", "1,2,3", "1,14,2,5", "5,6");
		System.out.println("是否执行该渠道任务 : "+NodeInfoManager.getInstance().isChannelDoTaskByNodeType(9l));
	}
	
}
